package com.easy.robot.framework

import ai.easy.robot.utils.logd
import ai.easy.robot.utils.loge
import android.app.Service
import android.content.Intent
import android.os.*
import java.util.concurrent.Semaphore
import kotlin.concurrent.thread

/**
 * 主服务，负责各节点消息订阅转发和节点管理
 */
class MasterService : Service() {

    companion object {

        const val NODE_MGR_REG = 1        //节点注册指令消息
        const val NODE_MGR_UN_REG = 2    //节点注销指令消息
        const val NODE_MGR_LIST = 3        //查询节点列表指令消息
        const val NODE_MGR_CLR = 4        //清除所有节点指令
        //const val NODE_MGR_REMOVE = 4

        const val NODE_MSG_PUB = 5        //节点发布消息
        const val NODE_MSG_SUB = 6        //节点订阅消息
        const val NODE_MSG_UN_SUB = 7    //取消订阅
        const val NODE_MSG_ON_REG = 8    //注册成功事件
        const val NODE_MSG_ON_NODE_CHANGED = 9   //节点列表发生变化事件
        //
        const val NODE_MSG = 16     //MasterService转发的消息
    }

    //@SinceKotlin("1.2.40")
    private lateinit var messenger: Messenger

    private class MyHandler(val master: MasterService, looper: Looper) : Handler(looper) {
        override fun handleMessage(msg: Message?) {
            when (msg?.what) {
                NODE_MGR_REG -> msg.replyTo?.let { master.registerNode("${msg.obj}", it) }
                NODE_MGR_UN_REG -> master.unregisterNode("${msg.obj}")
                NODE_MSG_SUB -> {
                    val a = msg.obj
                    logd("master sub ${a}")
                    if (a is Array<*>) {
                        val nodename = "${a[0]}"
                        val topic = "${a[1]}"
                        logd("master: node<${nodename}> sub ${topic}")
                        synchronized(master.nodeSubMap) {
                            master.nodeSubMap.getOrPut(nodename, { arrayListOf() })?.add(topic)
                        }
                    }
                }
                NODE_MSG_UN_SUB -> {
                    val topic = "${msg.obj}"
                    logd("master: node<> unsub ${topic}")
                    synchronized(master.nodeMap) {
                        master.nodeMap.forEach { name, mesenger ->
                            master.nodeSubMap[name]?.remove(topic)
                        }
                    }
                }
                NODE_MSG_PUB -> master.dispatchPubMsg("${msg.obj}", msg.data)
                NODE_MGR_LIST -> {
                    msg?.replyTo?.let {
                        val list = master.nodeMap.keys.toTypedArray()
                        val m = Message.obtain()
                        m.obj = list
                        it.send(m)
                    }
                }
                NODE_MGR_CLR -> master.clearAllNode()
                else -> {
                    //looper.quitSafely()
                }
            }
        }
    }

    private fun registerNode(nodeName: String, nodemsgr: Messenger) {
        synchronized(nodeMap) { nodeMap.put(nodeName, nodemsgr) }
        synchronized(nodeSubMap) { nodeSubMap.put(nodeName, arrayListOf()) }
        //
        logd("Node:${nodeMap.keys}")
        //
        val m = Message.obtain()
        m.what = NODE_MSG_ON_REG
        nodemsgr.send(m)
    }

    private fun unregisterNode(nodename: String) {
        synchronized(nodeMap) { nodeMap.remove(nodename) }
        synchronized(nodeSubMap) { nodeSubMap.remove(nodename) }
    }

    //转发消息
    private fun dispatchPubMsg(topic: String, msg: Bundle) {
        synchronized(nodeMap) {
            nodeMap.forEach { one ->
                val name = one.key
                val msgr = one.value
                val bond = nodeSubMap[name]?.any { it == topic } ?: false
                if (bond) {
                    //
                    logd("dispatch mseesge to topic: ${topic}")
                    val m = Message.obtain()
                    m.what = NODE_MSG
                    m.obj = topic
                    m.data = msg
                    //转发
                    msgr.send(m)
                }
            }
        }
    }

    private fun clearAllNode() {
        synchronized(nodeMap) { nodeMap.clear() }
        synchronized(nodeSubMap) { nodeSubMap.clear() }
    }

    val mtx = Semaphore(0)
    private lateinit var h: Handler
    override fun onCreate() {
        super.onCreate()
        logd("onCreate start")
        //
        thread(start = true, name = "master") {
            try {
                Looper.prepare()
                //TODO
                h = MyHandler(this, Looper.myLooper())
                //
                messenger = Messenger(h)

                mtx.release()
                //
                logd("start loop")
                Looper.loop()
                logd("stop loop")
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    override fun onDestroy() {
        //
        loge("service destory")
        h.looper.quit()

        super.onDestroy()
    }

    //节点映射表
    private val nodeMap: MutableMap<String, Messenger> = mutableMapOf()
    //订阅映射表
    private val nodeSubMap: MutableMap<String, MutableList<String>> = mutableMapOf()

    override fun onBind(intent: Intent?): IBinder = synchronized(this) {
        if (!this::messenger.isInitialized) {
            //mtx.wait()
            mtx.acquire()
        }
        messenger.binder
    }

}